use mongodb::{
    bson::{Document, doc},
    options::{ClientOptions, ServerApi, ServerApiVersion},
    sync::{Client, Collection, Database},
};

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
pub struct MyTrade {
    symbol:String,
    id:f64,
    orderId:f64,
    orderListId:i32,
    price:String,
    qty:String,
    quoteQty:String,
    commission:String,
    time:f64,
    isBuyer:bool,
    isMaker:bool,
    isBestMatch:bool,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Kline {
    symbol:String,
    openTime:f64,
    openPrice:String,
    highPrice:String,
    lowPrice:String,
    closePrice:String,
    volume:String,
    closeTime:f64,
    quteAssetVolume:String,
    numberOftrades:i32,
    takerBuyBaseAssetVolume:String,
    takerBuyQuoteAssetVolume:String,
    unUsedField:String,
}

pub struct DB {
    client: Client,
    database: Database,
    mytradecol: Collection<MyTrade>,
    kline12Col: Collection<Kline>,
}

impl DB {
    pub fn init_db(
        mongod_url: String,
        data_name: String,
    ) -> Result<DB, Box<dyn std::error::Error>> {
        let mut client_options = ClientOptions::parse(mongod_url).run().unwrap();

        let client = Client::with_options(client_options)?;
        let database = client.database(data_name.as_str());
        let mytradecol = database.collection("mytrades");
        let kline12Col = database.collection("h12klines");

        Ok(DB {
            client,
            database,
            mytradecol,
            kline12Col,
        })
    }

    pub fn find_trade_by_filter(&self, doc: Document,) -> Option<Vec<MyTrade>> {
        let mut cursor  = self.mytradecol.find(doc).run().unwrap();
        let mut result : Vec<MyTrade> = Vec::new();
        for kline in cursor {
            result.push(kline.unwrap());
        }
        Some(result)
    }

    pub fn find_kline_by_filter(&self, doc: Document,) -> Option<Vec<Kline>> {
        let mut cursor = self.kline12Col.find(doc).run().unwrap();
        let mut result : Vec<Kline> = Vec::new();
        for kline in cursor {
            result.push(kline.unwrap())
        }
        Some(result)
    }

}
